package com.tca.common.classload;

import com.tca.common.core.utils.ValidateUtils;
import lombok.extern.slf4j.Slf4j;
import sun.net.www.ParseUtil;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author zhoua
 * @date 2023/12/4 21:07
 */
@Slf4j
public class ThirdJarClassLoader extends URLClassLoader {

    /**
     * 用于单例模式, 即当前类加载器是否需要单例模式
     */
    private static Map<String, ThirdJarClassLoader> classLoaderMap = new ConcurrentHashMap<>();

    private ThirdJarClassLoader(URL[] urls) {
        super(urls);
    }

    /**
     * @return 自定义的类加载器
     * @throws IOException
     */
    public static ClassLoader getClassLoader(String directory, boolean isSingleton) throws Exception {
        if (isSingleton) {
            ThirdJarClassLoader thirdJarClassLoader = classLoaderMap.get(directory);
            if (ValidateUtils.isNotEmpty(thirdJarClassLoader)) {
                return thirdJarClassLoader;
            }
        }


        File file = new File(directory);

        log.info("第三方jar所在位置: {}", file.getAbsolutePath());

        if (!file.exists() || !file.isDirectory()) {
            throw new IOException("Please check if your path is correct!");
        }

        //获取所有的该目录下所有的jar文件
        List<File> jarList = Arrays.stream(Objects.requireNonNull(file.listFiles()))
                .filter((filePointer) -> filePointer.getName().endsWith(".jar"))
                .collect(Collectors.toList());

        if (ValidateUtils.isEmpty(jarList)) {
            throw new RuntimeException("There is no jar in the directory");
        }

        URL[] urls = new URL[jarList.size()];

        //将其所有的路径转换为URL
        for (int i = 0; i < urls.length; i++) {
            File jar = jarList.get(i).getCanonicalFile();
            urls[i] = ParseUtil.fileToEncodedURL(jar);
        }

        ThirdJarClassLoader thirdJarClassLoader = new ThirdJarClassLoader(urls);

        if (isSingleton) {
            classLoaderMap.put(directory, thirdJarClassLoader);
        }

        return thirdJarClassLoader;
    }

    /**
     * 默认使用单例模式
     * @param directory
     * @return
     * @throws Exception
     */
    public static ClassLoader getClassLoader(String directory) throws Exception {
        return getClassLoader(directory, true);
    }

}
